#ifndef Py_OBJECT_H
#define Py_OBJECT_H

#define PyObject_HEAD			\
	int ob_refcnt;			\
	struct _typeobject *ob_type;

#define PyObject_HEAD_INIT(type)	\
	1, type,

#define PyObject_VAR_HEAD		\
	PyObject_HEAD			\
	int ob_size; /* Number of items in variable part */


typedef struct _object {
  PyObject_HEAD
} PyObject;

typedef struct {
  PyObject_VAR_HEAD
} PyVarObject;

typedef PyObject * (*unaryfunc)(PyObject *);
typedef PyObject * (*binaryfunc)(PyObject *, PyObject *);
typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *);

typedef int (*inquiry)(PyObject *);
typedef int (*coercion)(PyObject **, PyObject **);

typedef PyObject *(*intargfunc)(PyObject *, int);
typedef PyObject *(*intintargfunc)(PyObject *, int, int);
typedef int(*intobjargproc)(PyObject *, int, PyObject *);
typedef int(*intintobjargproc)(PyObject *, int, int, PyObject *);
typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *);

typedef int (*getreadbufferproc)(PyObject *, int, void **);
typedef int (*getwritebufferproc)(PyObject *, int, void **);
typedef int (*getsegcountproc)(PyObject *, int *);
typedef int (*getcharbufferproc)(PyObject *, int, const char **);

typedef int (*objobjproc)(PyObject *, PyObject *);

typedef int (*visitproc)(PyObject *, void *);
typedef int (*traverseproc)(PyObject *, visitproc, void *);

typedef struct {
  binaryfunc nb_add;
  binaryfunc nb_subtract;
  binaryfunc nb_multiply;
  binaryfunc nb_divide;
  binaryfunc nb_remainder;
  binaryfunc nb_divmod;
  ternaryfunc nb_power;
  unaryfunc nb_negative;
  unaryfunc nb_positive;
  unaryfunc nb_absolute;
  inquiry nb_nonzero;
  unaryfunc nb_invert;
  binaryfunc nb_lshift;
  binaryfunc nb_rshift;
  binaryfunc nb_and;
  binaryfunc nb_xor;
  binaryfunc nb_or;
  coercion nb_coerce;
  unaryfunc nb_int;
  unaryfunc nb_long;
  unaryfunc nb_float;
  unaryfunc nb_oct;
  unaryfunc nb_hex;

  binaryfunc nb_inplace_add;
  binaryfunc nb_inplace_subtract;
  binaryfunc nb_inplace_multiply;
  binaryfunc nb_inplace_divide;
  binaryfunc nb_inplace_remainder;
  ternaryfunc nb_inplace_power;
  binaryfunc nb_inplace_lshift;
  binaryfunc nb_inplace_rshift;
  binaryfunc nb_inplace_and;
  binaryfunc nb_inplace_xor;
  binaryfunc nb_inplace_or;

  binaryfunc nb_floor_divide;
  binaryfunc nb_true_divide;
  binaryfunc nb_inplace_floor_divide;
  binaryfunc nb_inplace_true_divide;
} PyNumberMethods;

typedef struct {
  inquiry sq_length;
  binaryfunc sq_concat;
  intargfunc sq_repeat;
  intargfunc sq_item;
  intintargfunc sq_slice;
  intobjargproc sq_ass_item;
  intintobjargproc sq_ass_slice;
  objobjproc sq_contains;

  binaryfunc sq_inplace_concat;
  intargfunc sq_inplace_repeat;
} PySequenceMethods;

typedef struct {
  inquiry mp_length;
  binaryfunc mp_subscript;
  objobjargproc mp_ass_subscript;
} PyMappingMethods;

typedef struct {
  getreadbufferproc bf_getreadbuffer;
  getwritebufferproc bf_getwritebuffer;
  getsegcountproc bf_getsegcount;
  getcharbufferproc bf_getcharbuffer;
} PyBufferProcs;


typedef void (*freefunc)(void *);
typedef void (*destructor)(PyObject *);
typedef int (*printfunc)(PyObject *);
typedef PyObject *(*getattrfunc)(PyObject *, char *);
typedef PyObject *(*getattrofunc)(PyObject *, PyObject *);
typedef int (*setattrfunc)(PyObject *, char *, PyObject *);
typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *);
typedef int (*cmpfunc)(PyObject *, PyObject *);
typedef PyObject *(*reprfunc)(PyObject *);
typedef long (*hashfunc)(PyObject *);
typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int);
typedef PyObject *(*getiterfunc) (PyObject *);
typedef PyObject *(*iternextfunc) (PyObject *);
typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *);
typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *);
typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
typedef PyObject *(*allocfunc)(struct _typeobject *, int);

typedef struct _typeobject {
  PyObject_VAR_HEAD
  char *tp_name; /* For printing, in format "<module>.<name>" */
  int tp_basicsize, tp_itemsize; /* For allocation */

  /* Methods to implement standard operations */

  destructor tp_dealloc;
  printfunc tp_print;
  getattrfunc tp_getattr;
  setattrfunc tp_setattr;
  cmpfunc tp_compare;
  reprfunc tp_repr;

  /* Method suites for standard classes */

  PyNumberMethods *tp_as_number;
  PySequenceMethods *tp_as_sequence;
  PyMappingMethods *tp_as_mapping;

  /* More standard operations (here for binary compatibility) */

  hashfunc tp_hash;
  ternaryfunc tp_call;
  reprfunc tp_str;
  getattrofunc tp_getattro;
  setattrofunc tp_setattro;

  /* Functions to access object as input/output buffer */
  PyBufferProcs *tp_as_buffer;

  /* Flags to define presence of optional/expanded features */
  long tp_flags;

  char *tp_doc; /* Documentation string */

  /* Assigned meaning in release 2.0 */
  /* call function for all accessible objects */
  traverseproc tp_traverse;

  /* delete references to contained objects */
  inquiry tp_clear;

  /* Assigned meaning in release 2.1 */
  /* rich comparisons */
  richcmpfunc tp_richcompare;

  /* weak reference enabler */
  long tp_weaklistoffset;

  /* Added in release 2.2 */
  /* Iterators */
  getiterfunc tp_iter;
  iternextfunc tp_iternext;

  /* Attribute descriptor and subclassing stuff */
  struct PyMethodDef *tp_methods;
  struct PyMemberDef *tp_members;
  struct PyGetSetDef *tp_getset;
  struct _typeobject *tp_base;
  PyObject *tp_dict;
  descrgetfunc tp_descr_get;
  descrsetfunc tp_descr_set;
  long tp_dictoffset;
  initproc tp_init;
  allocfunc tp_alloc;
  newfunc tp_new;
  freefunc tp_free; /* Low-level free-memory routine */
  inquiry tp_is_gc; /* For PyObject_IS_GC */
  PyObject *tp_bases;
  PyObject *tp_mro; /* method resolution order */
  PyObject *tp_cache;
  PyObject *tp_subclasses;
  PyObject *tp_weaklist;
  destructor tp_del;
} PyTypeObject;

PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *);
#define PyObject_TypeCheck(ob, tp) \
	((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp)))

PyAPI_DATA(PyTypeObject) PyType_Type;
PyAPI_DATA(PyTypeObject) PyBaseObject_Type;

PyAPI_FUNC(int) PyType_Ready(PyTypeObject *);

PyAPI_FUNC(int) PyObject_Print(PyObject *);

PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int);
PyAPI_FUNC(int) PyObject_RichCompareBool(PyObject *, PyObject *, int);

PyAPI_FUNC(long) PyObject_Hash(PyObject *);
PyAPI_FUNC(int) PyObject_IsTrue(PyObject *);

PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **);

extern int _PyObject_SlotCompare(PyObject *, PyObject *);

#define Py_TPFLAGS_CHECKTYPES (1L<<4)
#define Py_TPFLAGS_HAVE_RICHCOMPARE (1L<<5)
#define Py_TPFLAGS_HAVE_CLASS (1L<<8)

#define Py_TPFLAGS_READY (1L<<12)
#define Py_TPFLAGS_READYING (1L<<13)

#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0)

#define _Py_NewReference(op) (			\
	(op)->ob_refcnt = 1)

#define _Py_Dealloc(op) 
/* @@@ ((*(op)->ob_type->tp_dealloc)((PyObject *)(op))) */

#define Py_INCREF(op) (				\
	(op)->ob_refcnt++)

#define Py_DECREF(op)				\
	if (--(op)->ob_refcnt != 0)		\
		;				\
	else					\
		_Py_Dealloc((PyObject *)(op))

#define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)
#define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)

PyAPI_DATA(PyObject) _Py_NoneStruct;
#define Py_None (&_Py_NoneStruct)

PyAPI_DATA(PyObject) _Py_NotImplementedStruct;
#define Py_NotImplemented (&_Py_NotImplementedStruct)

#define Py_LT 0
#define Py_LE 1
#define Py_EQ 2
#define Py_NE 3
#define Py_GT 4
#define Py_GE 5

#endif /* !Py_OBJECT_H */
